﻿/*********************************************************************************
*
* Copyright (c) ReflectSoftware, Inc. All rights reserved. 
*
* See License.rtf in the solution root for license information.
*
**********************************************************************************/

using System;
using System.Collections.Generic;
using System.Diagnostics;

using Microsoft.Practices.EnterpriseLibrary.Logging;
using Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners;
using Microsoft.Practices.EnterpriseLibrary.Logging.Configuration;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;

using ReflectSoftware.Insight.Common;

namespace ReflectSoftware.Insight.Extensions.EnterpriseLibrary.Tracer
{    
    [ConfigurationElementType(typeof(CustomTraceListenerData))]
    public class RICustomTracer : CustomTraceListener
    {
        protected String _Name;
        protected RITraceListener FRITraceListener;
                
        //---------------------------------------------------------------------------
        /// <summary>
        /// Initializes a new instance of the <see cref="RICustomTracer"/> class.
        /// </summary>
        public RICustomTracer()
        {
            FRITraceListener = null;
            Name = "RICustomTracer";
        }

        //---------------------------------------------------------------------------
        /// <summary>
        /// Disposes the listener.
        /// </summary>
        protected void DisposeListener()
        {
            lock (this)
            {
                if (FRITraceListener != null)
                {
                    FRITraceListener.Dispose();
                    FRITraceListener = null;
                }
            }
        }

        //---------------------------------------------------------------------------
        /// <summary>
        /// Releases the unmanaged resources used by the <see cref="T:System.Diagnostics.TraceListener" /> and optionally releases the managed resources.
        /// </summary>
        /// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param>
        protected override void Dispose(bool disposing)
        {
            DisposeListener();
            base.Dispose(disposing);
        }

        //---------------------------------------------------------------------------
        /// <summary>
        /// When overridden in a derived class, closes the output stream so it no longer receives tracing or debugging output.
        /// </summary>
        public override void Close()
        {
            DisposeListener();
            base.Close();
        }

        //---------------------------------------------------------------------------
        /// <summary>
        /// Gets the listener.
        /// </summary>
        /// <value>
        /// The listener.
        /// </value>
        protected RITraceListener Listener
        {
            get
            {
                lock (this)
                {
                    if (FRITraceListener == null)
                    {
                        String instanceName = Attributes["Extension"] ?? "RITraceListener";
                        FRITraceListener = new RITraceListener(instanceName);
                    }
                }
                    
                return FRITraceListener;
            }
        }

        //---------------------------------------------------------------------------
        /// <summary>
        /// Writes trace information, a data object and event information to the listener specific output.
        /// </summary>
        /// <param name="eventCache">A <see cref="T:System.Diagnostics.TraceEventCache" /> object that contains the current process ID, thread ID, and stack trace information.</param>
        /// <param name="source">A name used to identify the output, typically the name of the application that generated the trace event.</param>
        /// <param name="eventType">One of the <see cref="T:System.Diagnostics.TraceEventType" /> values specifying the type of event that has caused the trace.</param>
        /// <param name="id">A numeric identifier for the event.</param>
        /// <param name="data">The trace data to emit.</param>
        /// <PermissionSet>
        ///   <IPermission class="System.Security.Permissions.EnvironmentPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />
        ///   <IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="UnmanagedCode" />
        ///   </PermissionSet>
        public override void TraceData(TraceEventCache eventCache, String source, TraceEventType eventType, Int32 id, Object data)
        {
            if (data is XmlLogEntry)
            {
                RITraceListenerData tData = new RITraceListenerData();
                tData.MessageType = MessageType.SendXML;
                tData.Message = (data as XmlLogEntry).Message;
                tData.Details = (data as XmlLogEntry).Xml.InnerXml;
                tData.ExtendedProperties = (data as XmlLogEntry).ExtendedProperties;
                
                Listener.TraceData(eventCache, source, eventType, id, tData);
            }
            else if (data is LogEntry)
            {
                RITraceListenerData tData = new RITraceListenerData() { Message = (data as LogEntry).Message };
                RITraceListener.PrepareListenerData(tData, eventType);
                tData.ExtendedProperties = (data as LogEntry).ExtendedProperties;

                Listener.TraceData(eventCache, source, eventType, id, tData);
            }
            else if (data is string)
            {
                Write(data as string);
            }
            else
            {
                base.TraceData(eventCache, source, eventType, id, data);
            }
        }

        //---------------------------------------------------------------------------
        /// <summary>
        /// Writes trace information, a message, and event information to the listener specific output.
        /// </summary>
        /// <param name="eventCache">A <see cref="T:System.Diagnostics.TraceEventCache" /> object that contains the current process ID, thread ID, and stack trace information.</param>
        /// <param name="source">A name used to identify the output, typically the name of the application that generated the trace event.</param>
        /// <param name="eventType">One of the <see cref="T:System.Diagnostics.TraceEventType" /> values specifying the type of event that has caused the trace.</param>
        /// <param name="id">A numeric identifier for the event.</param>
        /// <param name="message">A message to write.</param>
        /// <PermissionSet>
        ///   <IPermission class="System.Security.Permissions.EnvironmentPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />
        ///   <IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="UnmanagedCode" />
        ///   </PermissionSet>
        public override void TraceEvent(TraceEventCache eventCache, string source, TraceEventType eventType, int id, string message)
        {
            Listener.TraceEvent(eventCache, source, eventType, id, message);
        }

        //---------------------------------------------------------------------------
        /// <summary>
        /// Writes trace information, a formatted array of objects and event information to the listener specific output.
        /// </summary>
        /// <param name="eventCache">A <see cref="T:System.Diagnostics.TraceEventCache" /> object that contains the current process ID, thread ID, and stack trace information.</param>
        /// <param name="source">A name used to identify the output, typically the name of the application that generated the trace event.</param>
        /// <param name="eventType">One of the <see cref="T:System.Diagnostics.TraceEventType" /> values specifying the type of event that has caused the trace.</param>
        /// <param name="id">A numeric identifier for the event.</param>
        /// <param name="format">A format string that contains zero or more format items, which correspond to objects in the <paramref name="args" /> array.</param>
        /// <param name="args">An object array containing zero or more objects to format.</param>
        /// <PermissionSet>
        ///   <IPermission class="System.Security.Permissions.EnvironmentPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />
        ///   <IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="UnmanagedCode" />
        ///   </PermissionSet>
        public override void TraceEvent(TraceEventCache eventCache, string source, TraceEventType eventType, int id, string format, params object[] args)
        {
            Listener.TraceEvent(eventCache, source, eventType, id, format, args);
        }

        //---------------------------------------------------------------------------
        /// <summary>
        /// Fails the specified MSG.
        /// </summary>
        /// <param name="msg">The MSG.</param>
        public override void Fail(String msg)
        {
            Listener.Fail(msg);
        }

        //---------------------------------------------------------------------------
        /// <summary>
        /// Fails the specified MSG.
        /// </summary>
        /// <param name="msg">The MSG.</param>
        /// <param name="category">The category.</param>
        public override void Fail(String msg, String category)
        {
            Listener.Fail(msg, category);
        }

        //---------------------------------------------------------------------------
        /// <summary>
        /// Writes the specified MSG.
        /// </summary>
        /// <param name="msg">The MSG.</param>
        public override void Write(String msg)
        {
            Listener.Write(msg);
        }

        //---------------------------------------------------------------------------		
        /// <summary>
        /// Writes the specified obj.
        /// </summary>
        /// <param name="obj">The obj.</param>
        public override void Write(Object obj)
        {
            Listener.Write(obj);
        }

        //---------------------------------------------------------------------------
        /// <summary>
        /// Writes the specified MSG.
        /// </summary>
        /// <param name="msg">The MSG.</param>
        /// <param name="category">The category.</param>
        public override void Write(String msg, String category)
        {
            Listener.Write(msg, category);
        }

        //---------------------------------------------------------------------------
        /// <summary>
        /// Writes the specified obj.
        /// </summary>
        /// <param name="obj">The obj.</param>
        /// <param name="category">The category.</param>
        public override void Write(Object obj, String category)
        {
            Listener.Write(obj, category);
        }

        //---------------------------------------------------------------------------
        /// <summary>
        /// Writes the line.
        /// </summary>
        /// <param name="msg">The MSG.</param>
        public override void WriteLine(String msg)
        {
            Listener.WriteLine(msg);
        }

        //---------------------------------------------------------------------------
        /// <summary>
        /// Writes the line.
        /// </summary>
        /// <param name="obj">The obj.</param>
        public override void WriteLine(Object obj)
        {
            Listener.WriteLine(obj);
        }

        //---------------------------------------------------------------------------
        /// <summary>
        /// Writes the line.
        /// </summary>
        /// <param name="msg">The MSG.</param>
        /// <param name="category">The category.</param>
        public override void WriteLine(String msg, String category)
        {
            Listener.WriteLine(msg, category);
        }

        //---------------------------------------------------------------------------		
        /// <summary>
        /// Writes the line.
        /// </summary>
        /// <param name="obj">The obj.</param>
        /// <param name="category">The category.</param>
        public override void WriteLine(Object obj, String category)
        {
            Listener.WriteLine(obj, category);
        }

        //---------------------------------------------------------------------------		
        /// <summary>
        /// Gets or sets a name for this <see cref="T:System.Diagnostics.TraceListener" />.
        /// </summary>
        /// <returns>
        /// A name for this <see cref="T:System.Diagnostics.TraceListener" />. The default is an empty string ("").
        ///   </returns>
        public override String Name
        {
            get { return _Name; }            
            set { _Name = value; }            
        }

        //---------------------------------------------------------------------------		
        /// <summary>
        /// Gets a value indicating whether the trace listener is thread safe.
        /// </summary>
        /// <returns>true if the trace listener is thread safe; otherwise, false. The default is false.
        ///   </returns>
        public override bool IsThreadSafe
        {
            get { return true; }
        }
    }    
}
